<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="../">
<head>
  <meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>packs &mdash; The Logtalk Handbook v3.93.0-b01 documentation</title>
      <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
      <link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094" />
      <link rel="stylesheet" type="text/css" href="../_static/css/custom.css?v=396eccfe" />

  
  <!--[if lt IE 9]>
    <script src="../_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script src="../_static/jquery.js?v=5d32c60e"></script>
        <script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
        <script src="../_static/documentation_options.js?v=c8100655"></script>
        <script src="../_static/doctools.js?v=9a2dae69"></script>
        <script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
    <script src="../_static/js/theme.js"></script>
    <!-- begin favicon -->
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
    <link rel="manifest" href="/site.webmanifest" />
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
    <meta name="msapplication-TileColor" content="#355b95" />
    <meta name="theme-color" content="#ffffff" />
    <!-- end favicon -->
    
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="ports_profiler" href="ports_profiler.html" />
    <link rel="prev" title="make" href="make.html" />
   
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >

          
          
          <a href="../index.html" class="icon icon-home">
            The Logtalk Handbook
              <img src="../_static/logtalk.gif" class="logo" alt="Logo"/>
          </a>
              <div class="version">
                3.93.0
              </div>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
    
              <p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../userman/index.html">User Manual</a></li>
<li class="toctree-l1"><a class="reference internal" href="../refman/index.html">Reference Manual</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tutorial/index.html">Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Developer Tools</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="overview.html">Overview</a></li>
<li class="toctree-l2"><a class="reference internal" href="asdf.html"><code class="docutils literal notranslate"><span class="pre">asdf</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="assertions.html"><code class="docutils literal notranslate"><span class="pre">assertions</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="code_metrics.html"><code class="docutils literal notranslate"><span class="pre">code_metrics</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="dead_code_scanner.html"><code class="docutils literal notranslate"><span class="pre">dead_code_scanner</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="debug_messages.html"><code class="docutils literal notranslate"><span class="pre">debug_messages</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="debugger.html"><code class="docutils literal notranslate"><span class="pre">debugger</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="diagrams.html"><code class="docutils literal notranslate"><span class="pre">diagrams</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="doclet.html"><code class="docutils literal notranslate"><span class="pre">doclet</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="help.html"><code class="docutils literal notranslate"><span class="pre">help</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="issue_creator.html"><code class="docutils literal notranslate"><span class="pre">issue_creator</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="lgtdoc.html"><code class="docutils literal notranslate"><span class="pre">lgtdoc</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="lgtunit.html"><code class="docutils literal notranslate"><span class="pre">lgtunit</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="linter.html"><code class="docutils literal notranslate"><span class="pre">linter</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="make.html"><code class="docutils literal notranslate"><span class="pre">make</span></code></a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#"><code class="docutils literal notranslate"><span class="pre">packs</span></code></a><ul>
<li class="toctree-l3"><a class="reference internal" href="#requirements">Requirements</a></li>
<li class="toctree-l3"><a class="reference internal" href="#api-documentation">API documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="#loading">Loading</a></li>
<li class="toctree-l3"><a class="reference internal" href="#testing">Testing</a></li>
<li class="toctree-l3"><a class="reference internal" href="#usage">Usage</a></li>
<li class="toctree-l3"><a class="reference internal" href="#registries-and-packs-storage">Registries and packs storage</a></li>
<li class="toctree-l3"><a class="reference internal" href="#virtual-environments">Virtual environments</a></li>
<li class="toctree-l3"><a class="reference internal" href="#registry-specification">Registry specification</a></li>
<li class="toctree-l3"><a class="reference internal" href="#registry-handling">Registry handling</a></li>
<li class="toctree-l3"><a class="reference internal" href="#registry-development">Registry development</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-specification">Pack specification</a></li>
<li class="toctree-l3"><a class="reference internal" href="#encrypted-packs">Encrypted packs</a></li>
<li class="toctree-l3"><a class="reference internal" href="#signed-packs">Signed packs</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-urls-and-single-sign-on">Pack URLs and Single Sign-On</a></li>
<li class="toctree-l3"><a class="reference internal" href="#multiple-pack-versions">Multiple pack versions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-dependencies">Pack dependencies</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-portability">Pack portability</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-development">Pack development</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-handling">Pack handling</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pack-documentation">Pack documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="#pinning-registries-and-packs">Pinning registries and packs</a></li>
<li class="toctree-l3"><a class="reference internal" href="#testing-packs">Testing packs</a></li>
<li class="toctree-l3"><a class="reference internal" href="#security-considerations">Security considerations</a></li>
<li class="toctree-l3"><a class="reference internal" href="#best-practices">Best practices</a></li>
<li class="toctree-l3"><a class="reference internal" href="#installing-prolog-packs">Installing Prolog packs</a></li>
<li class="toctree-l3"><a class="reference internal" href="#help-with-warnings">Help with warnings</a></li>
<li class="toctree-l3"><a class="reference internal" href="#known-issues">Known issues</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="ports_profiler.html"><code class="docutils literal notranslate"><span class="pre">ports_profiler</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="profiler.html"><code class="docutils literal notranslate"><span class="pre">profiler</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="tutor.html"><code class="docutils literal notranslate"><span class="pre">tutor</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="wrapper.html"><code class="docutils literal notranslate"><span class="pre">wrapper</span></code></a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../libraries/index.html">Libraries</a></li>
<li class="toctree-l1"><a class="reference internal" href="../ports/index.html">Ports</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributions/index.html">Contributions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../bibliography.html">Bibliography</a></li>
<li class="toctree-l1"><a class="reference internal" href="../genindex.html">Index</a></li>
</ul>

    <p class="caption"><span class="caption-text">External Contents</span></p>
    <ul>
    <li class="toctree-l1"><a class="reference internal" href="../../apis/index.html">APIs</a></li>
    <li class="toctree-l1"><a class="reference internal" href="https://logtalk.org">Logtalk website</a></li>
    <li class="toctree-l1"><a class="reference internal" href="https://github.com/LogtalkDotOrg/logtalk3">GitHub repo</a></li>
    </ul>
  
        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../index.html">The Logtalk Handbook</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
          <li class="breadcrumb-item"><a href="index.html">Developer Tools</a></li>
      <li class="breadcrumb-item active"><code class="docutils literal notranslate"><span class="pre">packs</span></code></li>
      <li class="wy-breadcrumbs-aside">
              <a href="https://github.com/LogtalkDotOrg/logtalk3/blob/master/docs/handbook/sources/devtools/packs.rst" class="fa fa-github"> Edit on GitHub</a>
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <section id="packs">
<span id="library-packs"></span><h1><code class="docutils literal notranslate"><span class="pre">packs</span></code><a class="headerlink" href="#packs" title="Link to this heading"></a></h1>
<p>This tool provides predicates for downloading, installing, upgrading,
and uninstalling third-party libraries and applications, generically
known as <em>packs</em>. Collections of pack specifications are made available
using <em>registries</em>. Registries can be local to a system, publicly
shared, or private to a company (e.g., only available in a VPN). There
is no concept of a central registry. Users can decide which registries
they trust and want to use and add them using their published URLs. The
tool supports both pack checksums and signatures and takes several steps
to sanitize registry and pack specifications. As with other Logtalk
developer tools, portability is a main goal. This tool can be used with
any supported Prolog backend and run on both POSIX and Windows systems.
Moreover, this tool can be used not only for handling Logtalk packs but
also for Prolog only packs, thus providing a solution for sharing
portable resources between multiple systems.</p>
<p>A list of public Logtalk and Prolog pack registries is available at:</p>
<p><a class="reference external" href="https://github.com/LogtalkDotOrg/pack-registries">https://github.com/LogtalkDotOrg/pack-registries</a></p>
<p>This tool is in the beta stage of development. Feedback is most welcome.</p>
<section id="requirements">
<h2>Requirements<a class="headerlink" href="#requirements" title="Link to this heading"></a></h2>
<p>On POSIX systems (Linux, macOS, …), the following shell commands are
required:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">sha256sum</span></code> (provided by GNU <code class="docutils literal notranslate"><span class="pre">coreutils</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">curl</span></code> (default file downloader)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">wget</span></code> (alternative file downloader)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">bsdtar</span></code> (provided by <code class="docutils literal notranslate"><span class="pre">libarchive</span></code> or <code class="docutils literal notranslate"><span class="pre">libarchive-tools</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">gpg</span></code> (provided by <code class="docutils literal notranslate"><span class="pre">gnupg2</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">git</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">direnv</span></code> (when using virtual environments)</p></li>
</ul>
<p>The tool uses <code class="docutils literal notranslate"><span class="pre">bsdtar</span></code> instead of GNU <code class="docutils literal notranslate"><span class="pre">tar</span></code> so that it can
uncompress <code class="docutils literal notranslate"><span class="pre">.zip</span></code> archives (<code class="docutils literal notranslate"><span class="pre">unzip</span></code> doesn’t provide the desired
options that allow a simple and reliable solution for ignoring the
non-predictable name of the wrapper directory).</p>
<p>On Windows systems, the following shell commands are required:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">certutil.exe</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">curl.exe</span></code> (default file downloader)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">wget.exe</span></code> (alternative file downloader)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">tar.exe</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">gpg.exe</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">git.exe</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Set-PsEnv</span></code> (when using virtual environments)</p></li>
</ul>
<p>In recent Windows 10 builds, only <code class="docutils literal notranslate"><span class="pre">wget</span></code>, <code class="docutils literal notranslate"><span class="pre">gpg</span></code>, <code class="docutils literal notranslate"><span class="pre">git</span></code>, and
<code class="docutils literal notranslate"><span class="pre">Set-PsEnv</span></code> should require installation. You can download the GnuPG
software from:</p>
<p><a class="reference external" href="https://www.gnupg.org/">https://www.gnupg.org/</a></p>
<p>You can download Git from:</p>
<p><a class="reference external" href="https://gitforwindows.org">https://gitforwindows.org</a></p>
<p>You can download Wget from:</p>
<p><a class="reference external" href="https://eternallybored.org/misc/wget/">https://eternallybored.org/misc/wget/</a></p>
<p>You can also use Chocolatey to install the commands above:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> choco install gnupg git wget
</pre></div>
</div>
<p>To install <a class="reference external" href="https://github.com/rajivharris/Set-PsEnv">Set-PsEnv</a> from
the PowerShell Gallery:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="nv">PS</span><span class="o">&gt;</span> <span class="nv">Install</span><span class="o">-</span><span class="nv">Module</span> <span class="o">-</span><span class="nv">Name</span> <span class="nv">Set</span><span class="o">-</span><span class="nv">PsEnv</span>
</pre></div>
</div>
<p>On macOS systems, Apple bundles both <code class="docutils literal notranslate"><span class="pre">curl</span></code> and BSD <code class="docutils literal notranslate"><span class="pre">tar</span></code> (under the
name <code class="docutils literal notranslate"><span class="pre">tar</span></code>; you can simply create a <code class="docutils literal notranslate"><span class="pre">bsdtar</span></code> alias or install a more
recent version). The required commands can be easily installed using
MacPorts:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> sudo port install coreutils wget libarchive gnupg2 git direnv
</pre></div>
</div>
<p>Or using Homebrew:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> brew install coreutils wget libarchive gnupg2 git direnv
</pre></div>
</div>
<p>On Linux systems, use the distribution’s own package manager to install
any missing command. For example, in recent Ubuntu versions:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> sudo apt update
<span class="err">$</span> sudo apt install coreutils curl wget libarchive<span class="o">-</span>tools gnupg2 git direnv
</pre></div>
</div>
</section>
<section id="api-documentation">
<h2>API documentation<a class="headerlink" href="#api-documentation" title="Link to this heading"></a></h2>
<p>This tool API documentation is available at:</p>
<p><a class="reference external" href="../../apis/library_index.html#packs">../../apis/library_index.html#packs</a></p>
</section>
<section id="loading">
<h2>Loading<a class="headerlink" href="#loading" title="Link to this heading"></a></h2>
<p>This tool can be loaded using the query:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> <span class="k">logtalk_load</span>(packs(loader)).
</pre></div>
</div>
</section>
<section id="testing">
<h2>Testing<a class="headerlink" href="#testing" title="Link to this heading"></a></h2>
<p>To run the tool tests, use the query:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> <span class="k">logtalk_load</span>(packs(tester)).
</pre></div>
</div>
<p>The tests can be run without interfering with the user packs setup.</p>
</section>
<section id="usage">
<h2>Usage<a class="headerlink" href="#usage" title="Link to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">packs</span></code> tool loads at startup all the currently defined registry
and pack specifications (from the registries/packs storage directory;
see below). When no registry/pack setup exists, a new one is
automatically created.</p>
<p>The tool provides two main objects, <code class="docutils literal notranslate"><span class="pre">registries</span></code> and <code class="docutils literal notranslate"><span class="pre">packs</span></code>, for
handling, respectively, registries and packs. Both objects accept a
<code class="docutils literal notranslate"><span class="pre">help/0</span></code> message that describes the most common queries.</p>
</section>
<section id="registries-and-packs-storage">
<h2>Registries and packs storage<a class="headerlink" href="#registries-and-packs-storage" title="Link to this heading"></a></h2>
<p>The tool uses a directory specified using the <code class="docutils literal notranslate"><span class="pre">logtalk_packs</span></code> library
alias when defined (in a settings file or in a backend Prolog
initialization file). When this library alias is not defined, the tool
uses the value of the <code class="docutils literal notranslate"><span class="pre">LOGTALKPACKS</span></code> environment variable when
defined. Otherwise, it defaults to the <code class="docutils literal notranslate"><span class="pre">~/logtalk_packs</span></code> directory.
The actual directory can be retrieved by the query:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>logtalk_packs(<span class="nv">Directory</span>).
...
</pre></div>
</div>
<p>This directory holds sub-directories for registries, packs, and
archives. These sub-directories are automatically created when loading
the <code class="docutils literal notranslate"><span class="pre">packs</span></code> tool if they don’t exist. Users should not manually modify
the contents of these directories. Multiple and independent
registry/pack setups are possible using <em>virtual environments</em> as
explained next.</p>
<p>Your registries and packs setup can be saved and restored (e.g., in a
different system) by using the <code class="docutils literal notranslate"><span class="pre">packs::save/1-2</span></code> and
<code class="docutils literal notranslate"><span class="pre">packs::restore/1-2</span></code> predicates, as explained in the next section
about virtual environments. If necessary, before restoring, the
<code class="docutils literal notranslate"><span class="pre">packs::reset/0</span></code> predicate can be called to delete any defined
registries and installed packs.</p>
</section>
<section id="virtual-environments">
<h2>Virtual environments<a class="headerlink" href="#virtual-environments" title="Link to this heading"></a></h2>
<p>An application may require specific pack versions. These requirements
may differ between applications. Different applications may also have
conflicting requirements. Therefore, a <em>virtual environment</em> where an
application requirements are fulfilled may be required to develop and/or
run it. A virtual environment is essentially a registries/packs storage
directory.</p>
<p>Defining the <code class="docutils literal notranslate"><span class="pre">logtalk_packs</span></code> library alias in a settings file or
defining the <code class="docutils literal notranslate"><span class="pre">LOGTALKPACKS</span></code> environment variable before starting
Logtalk allows easy creation and switching between virtual environments.
By using a per-application settings file (or a per-application
environment variable definition), each application can thus use its own
virtual environment. The <code class="docutils literal notranslate"><span class="pre">settings.lgt</span></code> file can define the
<code class="docutils literal notranslate"><span class="pre">logtalk_packs</span></code> library alias using code such as:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">initialization</span>((
    <span class="k">logtalk_load_context</span>(directory, <span class="nv">Directory</span>),
    <span class="k">assertz</span>(<span class="k">logtalk_library_path</span>(logtalk_packs, <span class="nv">Directory</span>))
)).
</pre></div>
</div>
<p>The definition of the <code class="docutils literal notranslate"><span class="pre">logtalk_packs</span></code> library alias <strong>must</strong> always be
an atom and thus never use library notation (i.e., it must never depend
on other library aliases).</p>
<p>When a virtual environment also requires a specific Logtalk version
(e.g., the version used to test and certify it), this can be installed
as a pack from the official
<a class="reference external" href="https://github.com/LogtalkDotOrg/talkshow">talkshow</a> registry and
used by (re)defining the <code class="docutils literal notranslate"><span class="pre">LOGTALKHOME</span></code> and <code class="docutils literal notranslate"><span class="pre">LOGTALKUSER</span></code> environment
variables to point to its pack directory (which can be queried by using
the <code class="docutils literal notranslate"><span class="pre">packs::directory/2</span></code> message).</p>
<p>Experimental <code class="docutils literal notranslate"><span class="pre">lgtenv.sh</span></code> and <code class="docutils literal notranslate"><span class="pre">lgtenv.ps1</span></code> scripts are included to
simplify creating virtual environments. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> lgtenv <span class="o">-</span>d <span class="err">~</span><span class="o">/</span>my_venv <span class="o">-</span>c <span class="o">-</span>p logtalk_packs
<span class="err">$</span> cd <span class="err">~</span><span class="o">/</span>my_venv
direnv<span class="o">:</span> loading <span class="err">~</span><span class="o">/</span>my_venv<span class="o">/</span>.envrc
direnv<span class="o">:</span> export <span class="o">+</span><span class="nv">LOGTALKPACKS</span>
</pre></div>
</div>
<p>Type <code class="docutils literal notranslate"><span class="pre">lgtenv</span> <span class="pre">-h</span></code> for details on the script options.</p>
<p>These scripts require, respectively,
<a class="reference external" href="https://github.com/direnv/direnv">direnv</a> and
<a class="reference external" href="https://github.com/rajivharris/Set-PsEnv">Set-PsEnv</a> to be
installed. These utilities load and unload environment variables when
changing the current directory. On Windows systems, when using the
<code class="docutils literal notranslate"><span class="pre">lgtenv.ps1</span></code> script, you also need to redefine the PowerShell prompt
in a profile file (e.g., <code class="docutils literal notranslate"><span class="pre">$HOME\Documents\PowerShell\Profile.ps1</span></code>) to
mimic the functionality of <code class="docutils literal notranslate"><span class="pre">direnv</span></code> of automatically loading an
existing <code class="docutils literal notranslate"><span class="pre">.env</span></code> file when changing to its directory. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>function prompt <span class="k">{</span>
    <span class="nv">Set</span><span class="o">-</span><span class="nv">PsEnv</span>
    <span class="s">&#39;PS &#39;</span> <span class="o">+</span> <span class="err">$</span>(<span class="nv">Get</span><span class="o">-</span><span class="nv">Location</span>) <span class="o">+</span> <span class="s">&#39;&gt; &#39;</span>
<span class="k">}</span>
</pre></div>
</div>
<p>A virtual environment setup (i.e., the currently defined registries and
installed packs) can be saved into a file (e.g., <code class="docutils literal notranslate"><span class="pre">requirements.lgt</span></code>)
using the <code class="docutils literal notranslate"><span class="pre">packs::save/1</span></code> predicate:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>save(<span class="s">&#39;requirements.lgt&#39;</span>).
...
</pre></div>
</div>
<p>This query saves a listing of all the installed packs and their
registries. Using the saved file, the virtual environment setup can then
be restored using the <code class="docutils literal notranslate"><span class="pre">packs::restore/1-2</span></code> predicates. The file uses a
simple format with <code class="docutils literal notranslate"><span class="pre">registry/2</span></code>, <code class="docutils literal notranslate"><span class="pre">pack/3</span></code>, <code class="docutils literal notranslate"><span class="pre">pinned_registry/1</span></code>,
and <code class="docutils literal notranslate"><span class="pre">pinned_pack/1</span></code> facts (in this order) and can be manually created
or edited if necessary. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>registry(talkshow, <span class="s">&#39;https://github.com/LogtalkDotOrg/talkshow.git&#39;</span>).
pack(talkshow, logtalk, <span class="m">3</span><span class="o">:</span><span class="m">45</span><span class="o">:</span><span class="m">0</span>).
pack(talkshow, lflat, <span class="m">2</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">0</span>).
</pre></div>
</div>
<p>These files can be distributed with applications so that users can
easily fulfill application requirements by running the query once:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>restore(<span class="s">&#39;requirements.lgt&#39;</span>).
</pre></div>
</div>
<p>Subsequently, the application <code class="docutils literal notranslate"><span class="pre">loader.lgt</span></code> file can then load the
required packs using their loader files:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">initialization</span>((
    <span class="c">% load required packs</span>
    <span class="k">logtalk_load</span>(foo(loader)),
    <span class="k">logtalk_load</span>(bar(loader)),
    ...
    <span class="c">% load application files</span>
    ...
)).
</pre></div>
</div>
<p>Note that restoring encrypted registries or encrypted packs requires
entering the required passphrases. Although the <code class="docutils literal notranslate"><span class="pre">restore/2</span></code> predicate
accepts a list of options that include the <code class="docutils literal notranslate"><span class="pre">gpg/1</span></code> option, this only
allows specifying a single and common passphrase when interactive
entering of passphrases is not convenient or possible.</p>
</section>
<section id="registry-specification">
<h2>Registry specification<a class="headerlink" href="#registry-specification" title="Link to this heading"></a></h2>
<p>A registry is a git remote repo that can be cloned, a downloadable or
local archive, or a local directory containing a Logtalk loader file
that loads source files defining the registry itself and the packs it
provides. The registry name is ideally a valid unquoted atom. The
registry directory must contain at least two Logtalk source files:</p>
<ul class="simple">
<li><p>A file defining an object named after the registry with a
<code class="docutils literal notranslate"><span class="pre">_registry</span></code> suffix, implementing the <code class="docutils literal notranslate"><span class="pre">registry_protocol</span></code>. This
naming convention helps prevent name conflicts.</p></li>
<li><p>A loader file (named <code class="docutils literal notranslate"><span class="pre">loader.lgt</span></code> or <code class="docutils literal notranslate"><span class="pre">loader.logtalk</span></code>) that loads
the registry object file and all pack object files.</p></li>
</ul>
<p>An example of a registry specification object would be:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(jdoe_awesome_packs_registry,
    <span class="k">implements</span>(registry_protocol)).

<span class="p">    :- </span><span class="k">info</span>([
        version <span class="k">is</span> <span class="m">1</span><span class="o">:</span><span class="m">0</span><span class="o">:</span><span class="m">0</span>,
        author <span class="k">is</span> <span class="s">&#39;John Doe&#39;</span>,
        date <span class="k">is</span> <span class="m">2021</span><span class="o">-</span><span class="m">10</span><span class="o">-</span><span class="m">18</span>,
        comment <span class="k">is</span> <span class="s">&#39;John Doe awesome packs registry spec.&#39;</span>
    ]).

    name(jdoe_awesome_packs).

    description(<span class="s">&#39;John Doe awesome packs&#39;</span>).

    home(<span class="s">&#39;https://example.com/jdoe_awesome_packs&#39;</span>).

    clone(<span class="s">&#39;https://github.com/jdoe/jdoe_awesome_packs.git&#39;</span>).

    archive(<span class="s">&#39;https://github.com/jdoe/jdoe_awesome_packs/archive/main.zip&#39;</span>).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>Optionally, the registry object can also define a <code class="docutils literal notranslate"><span class="pre">note(Action,</span> <span class="pre">Note)</span></code>
predicate. The <code class="docutils literal notranslate"><span class="pre">Action</span></code> argument is an atom: <code class="docutils literal notranslate"><span class="pre">add</span></code>, <code class="docutils literal notranslate"><span class="pre">update</span></code>, or
<code class="docutils literal notranslate"><span class="pre">delete</span></code>. The <code class="docutils literal notranslate"><span class="pre">Note</span></code> argument is also an atom. The tool will print
any available notes when executing one of the registry actions. See the
<code class="docutils literal notranslate"><span class="pre">registry_protocol</span></code> documentation for more details.</p>
<p>The registry directory should also contain <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> and <code class="docutils literal notranslate"><span class="pre">README.md</span></code>
files (individual packs can use a different license, however). The path
to the <code class="docutils literal notranslate"><span class="pre">README.md</span></code> file is printed when the registry is added. It can
also be queried using the <code class="docutils literal notranslate"><span class="pre">registries::directory/2</span></code> predicate. The
<code class="docutils literal notranslate"><span class="pre">NOTES.md</span></code> file name can also be used in alternative to the
recommended <code class="docutils literal notranslate"><span class="pre">README.md</span></code> file name.</p>
<p>Summarizing the required directory structure using the above example
(note that the registry and pack specification files are named after the
objects):</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>jdoe_awesome_packs
    <span class="nv">LICENSE</span>
    <span class="nv">README</span>.md
    jdoe_awesome_packs_registry.lgt
    loader.lgt
    foo_pack.lgt
    bar_pack.lgt
    ...
</pre></div>
</div>
<p>With the contents of the <code class="docutils literal notranslate"><span class="pre">loader.lgt</span></code> file being:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">initialization</span>((
    <span class="k">logtalk_load</span>(jdoe_awesome_packs_registry),
    <span class="k">logtalk_load</span>(foo_pack),
    <span class="k">logtalk_load</span>(bar_pack),
    ...
)).
</pre></div>
</div>
<p>It would be, of course, possible to have all objects in a single source
file. But having a file per-object and a loader file helps maintenance,
and it’s also a tool requirement for applying safety procedures to the
source file contents and thus successfully loading the registry and pack
specs.</p>
<p>As registries are git repos in the most common case, and thus adding
them performs a git repo cloning, they should only contain the strictly
required files.</p>
</section>
<section id="registry-handling">
<h2>Registry handling<a class="headerlink" href="#registry-handling" title="Link to this heading"></a></h2>
<p>Registries can be added using the <code class="docutils literal notranslate"><span class="pre">registries::add/1-3</span></code> predicates,
which take a registry URL. Using the example above:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> registries<span class="o">::</span>add(<span class="s">&#39;https://github.com/jdoe/jdoe_awesome_packs.git&#39;</span>).
</pre></div>
</div>
<p>HTTPS URLs must end with either a <code class="docutils literal notranslate"><span class="pre">.git</span></code> extension or an archive
extension (same valid extensions as for pack archives, including <code class="docutils literal notranslate"><span class="pre">gpg</span></code>
encrypted). Git cloning URLs are preferred as they simplify updating
registries. But a registry can also be made available via a local
directory (using a <code class="docutils literal notranslate"><span class="pre">file://</span></code> URL) or a downloadable archive (using a
<code class="docutils literal notranslate"><span class="pre">https://</span></code> URL).</p>
<p>For registries made available using an archive, the
<code class="docutils literal notranslate"><span class="pre">registries::add/2-3</span></code> predicates <strong>must</strong> be used as the registry name
cannot in general be inferred from the URL basename or from the archived
directory name. The registry argument must also be the declared registry
name in the registry specification object. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> registries<span class="o">::</span>add(
        jdoe_awesome_packs,
        <span class="s">&#39;https://github.com/jdoe/jdoe_awesome_packs/archive/main.zip&#39;</span>
     ).
</pre></div>
</div>
<p>When a registry may be already defined, you can use the <code class="docutils literal notranslate"><span class="pre">update(true)</span></code>
option to ensure that the registry will be updated to its latest
definition:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> registries<span class="o">::</span>add(
        jdoe_awesome_packs,
        <span class="s">&#39;https://github.com/jdoe/jdoe_awesome_packs/archive/main.zip&#39;</span>,
        [update(<span class="k">true</span>)]
     ).
</pre></div>
</div>
<p>The added registries can be listed using the <code class="docutils literal notranslate"><span class="pre">registries::list/0</span></code>
predicate:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> registries<span class="o">::</span>list.

<span class="c">% Defined registries:</span>
<span class="c">%   jdoe_awesome_packs (git)</span>
<span class="c">%   ...</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">registries::describe/1</span></code> predicate can be used to print the
details of a registry:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> registries<span class="o">::</span>describe(jdoe_awesome_packs).

<span class="c">% Registry:    jdoe_awesome_packs</span>
<span class="c">% Description: John Doe awesome packs</span>
<span class="c">% Home:        https://example.com/jdoe_awesome_packs</span>
<span class="c">% Cloning URL: https://github.com/jdoe/jdoe_awesome_packs.git</span>
<span class="c">% Archive URL: https://github.com/jdoe/jdoe_awesome_packs/archive/main.zip</span>
</pre></div>
</div>
<p>To update all registries, use the <code class="docutils literal notranslate"><span class="pre">registries::update/0</span></code> predicate. To
update a single registry, use the <code class="docutils literal notranslate"><span class="pre">registries::update/1-2</span></code> predicates.
After updating, you can use the <code class="docutils literal notranslate"><span class="pre">packs::outdated/0-1</span></code> predicates to
list any outdated packs.</p>
<p>Registries can also be deleted using the <code class="docutils literal notranslate"><span class="pre">registries::delete/1-2</span></code>
predicate. By default, any registries with installed packs cannot be
deleted. If you force deletion (by using the <code class="docutils literal notranslate"><span class="pre">force(true)</span></code> option),
you can use the <code class="docutils literal notranslate"><span class="pre">packs::orphaned/0</span></code> predicate to list any orphaned
packs that are installed.</p>
<p>See the tool API documentation on the
<a class="reference external" href="../../docs/registries_0.html">registries</a> object for other useful
predicates.</p>
</section>
<section id="registry-development">
<h2>Registry development<a class="headerlink" href="#registry-development" title="Link to this heading"></a></h2>
<p>To simplify registry development and testing, use a local directory and
a <code class="docutils literal notranslate"><span class="pre">file://</span></code> URL when calling the <code class="docutils literal notranslate"><span class="pre">registries::add/1</span></code> predicate. For
example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> registries<span class="o">::</span>add(<span class="s">&#39;file:///home/jdoe/work/my_pack_collection&#39;</span>).
</pre></div>
</div>
<p>If the directory is a git repo, the tool will clone it when adding it.
Otherwise, the files in the directory are copied to the registry
definition directory. This allows the registry to be added and deleted
without consequences for the original registry source files.</p>
<p>To check your registry specifications, use the <code class="docutils literal notranslate"><span class="pre">registries::lint/0-1</span></code>
predicates after adding the registry.</p>
</section>
<section id="pack-specification">
<h2>Pack specification<a class="headerlink" href="#pack-specification" title="Link to this heading"></a></h2>
<p>A pack is specified using a Logtalk source file defining an object that
implements the <code class="docutils literal notranslate"><span class="pre">pack_protocol</span></code>. The source file should be named after
the pack with a <code class="docutils literal notranslate"><span class="pre">_pack</span></code> suffix. This naming convention helps prevent
name conflicts, notably with the pack’s own objects. The file must be
available from a declared pack registry (by having the registry loader
file loading it). The pack name is preferably a valid unquoted atom. An
example of a pack specification object would be:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(lflat_pack,
    <span class="k">implements</span>(pack_protocol)).

<span class="p">    :- </span><span class="k">info</span>([
        version <span class="k">is</span> <span class="m">1</span><span class="o">:</span><span class="m">0</span><span class="o">:</span><span class="m">0</span>,
        author <span class="k">is</span> <span class="s">&#39;Paulo Moura&#39;</span>,
        date <span class="k">is</span> <span class="m">2021</span><span class="o">-</span><span class="m">10</span><span class="o">-</span><span class="m">18</span>,
        comment <span class="k">is</span> <span class="s">&#39;L-FLAT - Logtalk Formal Language and Automata Toolkit pack spec.&#39;</span>
    ]).

    name(lflat).

    description(<span class="s">&#39;L-FLAT - Logtalk Formal Language and Automata Toolkit&#39;</span>).

    license(<span class="s">&#39;MIT&#39;</span>).

    home(<span class="s">&#39;https://github.com/l-flat/lflat&#39;</span>).

    version(
        <span class="m">2</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">0</span>,
        stable,
        <span class="s">&#39;https://github.com/l-flat/lflat/archive/refs/tags/v2.1.0.tar.gz&#39;</span>,
        sha256 <span class="o">-</span> <span class="s">&#39;9c298c2a08c4e2a1972c14720ef1498e7f116c7cd8bf7702c8d22d8ff549b6a1&#39;</span>,
        [logtalk <span class="o">@&gt;=</span> <span class="m">3</span><span class="o">:</span><span class="m">42</span><span class="o">:</span><span class="m">0</span>],
        all
    ).

    version(
        <span class="m">2</span><span class="o">:</span><span class="m">0</span><span class="o">:</span><span class="m">2</span>,
        stable,
        <span class="s">&#39;https://github.com/l-flat/lflat/archive/refs/tags/v2.0.2.tar.gz&#39;</span>,
        sha256 <span class="o">-</span> <span class="s">&#39;8774b3863efc03bb6c284935885dcf34f69f115656d2496a33a446b6199f3e19&#39;</span>,
        [logtalk <span class="o">@&gt;=</span> <span class="m">3</span><span class="o">:</span><span class="m">36</span><span class="o">:</span><span class="m">0</span>],
        all
    ).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">license/1</span></code> argument must be an atom and should, whenever
possible, be a license identifier as specified in the <a class="reference external" href="https://spdx.org/licenses/">SPDX
standard</a>.</p>
<p>Optionally, the pack object can also define a
<code class="docutils literal notranslate"><span class="pre">note(Action,</span> <span class="pre">Version,</span> <span class="pre">Note)</span></code> predicate. The <code class="docutils literal notranslate"><span class="pre">Action</span></code> argument is an
atom: <code class="docutils literal notranslate"><span class="pre">install</span></code>, <code class="docutils literal notranslate"><span class="pre">update</span></code>, or <code class="docutils literal notranslate"><span class="pre">uninstall</span></code>. The <code class="docutils literal notranslate"><span class="pre">Note</span></code> argument
is also an atom. The tool will print any available notes when executing
one of the registry actions. See the <code class="docutils literal notranslate"><span class="pre">pack_protocol</span></code> documentation for
more details.</p>
<p>The pack sources must be available either as a local directory (when
using a <code class="docutils literal notranslate"><span class="pre">file://</span></code> URL) or for downloading as a supported archive. The
checksum for the archive must use the SHA-256 hash algorithm
(<code class="docutils literal notranslate"><span class="pre">sha256</span></code>). The pack may optionally be signed. Supported archive
formats and extensions are:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">.zip</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.tgz</span></code>, <code class="docutils literal notranslate"><span class="pre">.tar.gz</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.tbz2</span></code>, <code class="docutils literal notranslate"><span class="pre">.tar.bz2</span></code></p></li>
</ul>
<p>Also, for encrypted packs, all the extensions above with a <code class="docutils literal notranslate"><span class="pre">.gpg</span></code>
suffix (e.g., <code class="docutils literal notranslate"><span class="pre">.zip.gpg</span></code>).</p>
<p>The pack sources should contain <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>, <code class="docutils literal notranslate"><span class="pre">README.md</span></code> (or
<code class="docutils literal notranslate"><span class="pre">NOTES.md</span></code>), and <code class="docutils literal notranslate"><span class="pre">loader.lgt</span></code> (or <code class="docutils literal notranslate"><span class="pre">loader.logtalk</span></code>) files.
Ideally, it should also contain a <code class="docutils literal notranslate"><span class="pre">tester.lgt</span></code> (<code class="docutils literal notranslate"><span class="pre">tester.logtalk</span></code>)
file. The path to the <code class="docutils literal notranslate"><span class="pre">README.md</span></code> file is printed when the pack is
installed or updated. It can also be queried using the
<code class="docutils literal notranslate"><span class="pre">packs::directory/2</span></code> predicate.</p>
</section>
<section id="encrypted-packs">
<h2>Encrypted packs<a class="headerlink" href="#encrypted-packs" title="Link to this heading"></a></h2>
<p>Packs can be <code class="docutils literal notranslate"><span class="pre">gpg</span></code> encrypted, with a choice of passphrase-based
encryption, key-based encryption, or both. Encrypted pack archives must
always have a <code class="docutils literal notranslate"><span class="pre">.gpg</span></code> extension. For example, to encrypt a pack archive
with a symmetric cipher using a passphrase:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> tar <span class="o">-</span>cvzf <span class="o">-</span> my_pack | gpg <span class="o">-</span>c <span class="o">--</span>cipher<span class="o">-</span>algo <span class="nv">AES256</span> <span class="o">&gt;</span> v1.<span class="m">2.1</span>.tar.gz.gpg
</pre></div>
</div>
<p>In this case, the passphrase would need to be securely communicated to
any users installing or updating the pack.</p>
<p>See the <code class="docutils literal notranslate"><span class="pre">gpg</span></code> documentation for full details on encrypting and
decrypting archives. If you get a “gpg: problem with the agent:
Inappropriate ioctl for device” error message with the command above,
try:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> export <span class="nv">GPG_TTY</span><span class="o">=</span><span class="err">$</span>(tty)
</pre></div>
</div>
</section>
<section id="signed-packs">
<h2>Signed packs<a class="headerlink" href="#signed-packs" title="Link to this heading"></a></h2>
<p>Packs can be <code class="docutils literal notranslate"><span class="pre">gpg</span></code> signed. Detached signature files are assumed and
expected to share the name of the archive and use <code class="docutils literal notranslate"><span class="pre">.asc</span></code> or <code class="docutils literal notranslate"><span class="pre">.sig</span></code>
extensions. For example, if the pack archive name is <code class="docutils literal notranslate"><span class="pre">v1.0.0.tar.gz</span></code>,
the signature file must be named <code class="docutils literal notranslate"><span class="pre">v1.0.0.tar.gz.asc</span></code> or
<code class="docutils literal notranslate"><span class="pre">v1.0.0.tar.gz.sig</span></code>. When the <code class="docutils literal notranslate"><span class="pre">checksig(true)</span></code> option is used, the
signature file is automatically downloaded using a URL constructed from
the pack archive URL. When both <code class="docutils literal notranslate"><span class="pre">.asc</span></code> and <code class="docutils literal notranslate"><span class="pre">.sig</span></code> files exist, the
<code class="docutils literal notranslate"><span class="pre">.asc</span></code> file is used. An example of signing a pack and creating the
<code class="docutils literal notranslate"><span class="pre">.asc</span></code> file (assuming the default signing key) is:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> gpg <span class="o">--</span>armor <span class="o">--</span>detach<span class="o">-</span>sign v1.<span class="m">0.0</span>.tar.gz
</pre></div>
</div>
<p>To create instead a <code class="docutils literal notranslate"><span class="pre">.sig</span></code> file:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> gpg <span class="o">--</span>detach<span class="o">-</span>sign v1.<span class="m">0.0</span>.tar.gz
</pre></div>
</div>
<p>See the <code class="docutils literal notranslate"><span class="pre">gpg</span></code> documentation for full details on signing archives and
sharing the public keys required to verify the signatures.</p>
</section>
<section id="pack-urls-and-single-sign-on">
<h2>Pack URLs and Single Sign-On<a class="headerlink" href="#pack-urls-and-single-sign-on" title="Link to this heading"></a></h2>
<p>Typically, pack archive download URLs are HTTPS URLs and handled using
<code class="docutils literal notranslate"><span class="pre">curl</span></code>. It’s also possible to use <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">archive</span></code> to download pack
archives, provided that the server supports it (as of this writing,
Bitbucket and GitLab public hosting services support it but not GitHub).
Using <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">archive</span></code> is specially useful when the packs registry is
hosted on a server using Single Sign-On (SSO) for authentication. In
this case, HTTPS URLs can only be handled by <code class="docutils literal notranslate"><span class="pre">curl</span></code> by passing a token
(see below for an example). When the user has setup SSH keys to
authenticate to the packs registry server, <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">archive</span></code> simplifies
pack installation, providing a better user experience. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>version(
    <span class="m">1</span><span class="o">:</span><span class="m">0</span><span class="o">:</span><span class="m">1</span>,
    stable,
    <span class="s">&#39;git@gitlab.com:me/foo.git/v1.0.1.zip&#39;</span>,
    sha256 <span class="o">-</span> <span class="s">&#39;0894c7cdb8968b6bbcf00e3673c1c16cfa98232573af30ceddda207b20a7a207&#39;</span>,
    [logtalk <span class="o">@&gt;=</span> <span class="m">3</span><span class="o">:</span><span class="m">36</span><span class="o">:</span><span class="m">0</span>],
    all
).
</pre></div>
</div>
<p>The pseudo-URL must be the concatenation of the SSH repo cloning URL
with the archive name. The archive name must be the concatenation of a
valid tag with a supported archive extension. SSH repo cloning URLs use
the format:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>git<span class="o">@&lt;</span>hostname<span class="o">&gt;:</span>path<span class="o">/</span>to<span class="o">/</span>project.git
</pre></div>
</div>
<p>They can usually be easily copied from the hosting service repo webpage.
To compute the checksum, you must first download the archive. For
example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> git archive <span class="o">--</span>output<span class="o">=</span>foo<span class="o">-</span>v1.<span class="m">0.1</span>.zip <span class="o">--</span>remote<span class="o">=</span>git<span class="o">@</span>gitlab.com<span class="o">:</span>me<span class="o">/</span>foo.git v1.<span class="m">0.1</span>
<span class="err">$</span> openssl sha256 foo<span class="o">-</span>v1.<span class="m">0.1</span>.zip
</pre></div>
</div>
<p>Be sure to use a format that is supported by both the <code class="docutils literal notranslate"><span class="pre">packs</span></code> tool and
the <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">archive</span></code> command (the format is inferred from the
<code class="docutils literal notranslate"><span class="pre">--output</span></code> option). Do not download the archive from the web interface
of the git hosting service in order to compute the checksum. Different
implementations of the archiving and compressing algorithms may be used,
resulting in mismatched checksums.</p>
<p>Users installing packs available using <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">archive</span></code> URLs are advised
to run a SSH agent to avoid being prompted for passwords when installing
or updating packs. They must also upload their SSH public keys to the
pack provider hosts.</p>
</section>
<section id="multiple-pack-versions">
<h2>Multiple pack versions<a class="headerlink" href="#multiple-pack-versions" title="Link to this heading"></a></h2>
<p>A pack may specify multiple versions. Each version is described using a
<code class="docutils literal notranslate"><span class="pre">version/6</span></code> predicate clause as illustrated in the example above. The
versions must be listed in order from newest to oldest. For details, see
the <code class="docutils literal notranslate"><span class="pre">pack_protocol</span></code> API documentation.</p>
<p>Listing multiple versions allows the pack specification to be updated
(by updating its registry) without forcing existing users into
installing (or updating to) the latest version of the pack. It allows
different applications depending on different pack versions to continue
to be built and deployed.</p>
<p>The pack version is complemented by the pack status. Valid values are
<code class="docutils literal notranslate"><span class="pre">stable</span></code>, <code class="docutils literal notranslate"><span class="pre">rc</span></code>, <code class="docutils literal notranslate"><span class="pre">beta</span></code>, <code class="docutils literal notranslate"><span class="pre">alpha</span></code>, <code class="docutils literal notranslate"><span class="pre">experimental</span></code>, and
<code class="docutils literal notranslate"><span class="pre">deprecated</span></code>. Packs with a <code class="docutils literal notranslate"><span class="pre">experimental</span></code> or <code class="docutils literal notranslate"><span class="pre">deprecated</span></code> status
are <strong>never</strong> installed by default when using the install and update
predicates unless their version is explicitly specified. When updating
packs, we can restrict the valid status of the updates using the
<code class="docutils literal notranslate"><span class="pre">status/1</span></code> option. For example, we can ensure that we only update to
new stable pack versions by using the option <code class="docutils literal notranslate"><span class="pre">status([stable])</span></code>.</p>
</section>
<section id="pack-dependencies">
<h2>Pack dependencies<a class="headerlink" href="#pack-dependencies" title="Link to this heading"></a></h2>
<p>Pack dependencies on other packs can be specified using a list of
<code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">Operator</span> <span class="pre">Version</span></code> terms where <code class="docutils literal notranslate"><span class="pre">Operator</span></code> is a
standard term comparison operator:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">&#64;&gt;=</span> <span class="pre">Version</span></code> - the pack requires a dependency with a
version equal or above the specified one. For example,
<code class="docutils literal notranslate"><span class="pre">logtalk</span> <span class="pre">&#64;&gt;=</span> <span class="pre">3:36:0</span></code> means that the pack requires Logtalk 3.36.0 or
a later version.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">&#64;=&lt;</span> <span class="pre">Version</span></code> - the pack requires a dependency with a
version up to the specified one. For example, <code class="docutils literal notranslate"><span class="pre">common::bits</span> <span class="pre">&#64;=&lt;</span> <span class="pre">2:1</span></code>
means that the pack requires a <code class="docutils literal notranslate"><span class="pre">common::bits</span></code> pack up to 2.1. This
includes all previous versions and also all patches for version 2.1
(e.g., 2.1.7, 2.1.8, …) but not version 2.2 or newer.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">&#64;&lt;</span> <span class="pre">Version</span></code> - the pack requires a dependency with
version older than the specified one. For example,
<code class="docutils literal notranslate"><span class="pre">common::bits</span> <span class="pre">&#64;&lt;</span> <span class="pre">3</span></code> means that the pack requires a <code class="docutils literal notranslate"><span class="pre">common::bits</span></code>
2.x or older version.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">&#64;&gt;</span> <span class="pre">Version</span></code> - the pack requires a dependency with
version newer than the specified one. For example,
<code class="docutils literal notranslate"><span class="pre">common::bits</span> <span class="pre">&#64;&gt;</span> <span class="pre">2:4</span></code> means that the pack requires a
<code class="docutils literal notranslate"><span class="pre">common::bits</span></code> 2.5 or newer version.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">==</span> <span class="pre">Version</span></code> - the pack requires a dependency with a
specific version. For example, <code class="docutils literal notranslate"><span class="pre">common::bits</span> <span class="pre">==</span> <span class="pre">2:1</span></code> means that the
pack requires a <code class="docutils literal notranslate"><span class="pre">common::bits</span></code> pack version 2.1.x (thus, from
version 2.1.0 to the latest patch for version 2.1).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Registry::Pack</span> <span class="pre">\==</span> <span class="pre">Version</span></code> - the pack requires a dependency with
any version other than the one specified. For example,
<code class="docutils literal notranslate"><span class="pre">common::bits</span> <span class="pre">\==</span> <span class="pre">2.1</span></code> means that the pack requires a
<code class="docutils literal notranslate"><span class="pre">common::bits</span></code> pack version other than any 2.1.x version.</p></li>
</ul>
<p>To specify <em>range</em> dependencies by using two consecutive elements with
the lower bound followed by the upper bound. For example,
<code class="docutils literal notranslate"><span class="pre">common::bits</span> <span class="pre">&#64;&gt;=</span> <span class="pre">2,</span> <span class="pre">common::bits</span> <span class="pre">&#64;&lt;</span> <span class="pre">3</span></code> means all <code class="docutils literal notranslate"><span class="pre">common::bits</span></code> 2.x
versions but not older or newer major versions.</p>
<p>It’s also possible to specify <em>alternative</em> dependencies using the
<code class="docutils literal notranslate"><span class="pre">(;)/2</span></code> operator. For example,
<code class="docutils literal notranslate"><span class="pre">(common::bits</span> <span class="pre">==</span> <span class="pre">1:9;</span> <span class="pre">common::bits</span> <span class="pre">&#64;&gt;=</span> <span class="pre">2:3)</span></code> means either
<code class="docutils literal notranslate"><span class="pre">common::bits</span></code> 1.9.x versions or 2.3.x and later versions.
Alternatives should be listed in decreasing order of preference.</p>
<p>When a pack also depends on a Logtalk or backend version, the name
<code class="docutils literal notranslate"><span class="pre">logtalk</span></code> or the backend identifier atom can be used in place of
<code class="docutils literal notranslate"><span class="pre">Registry::Pack</span></code> (see below for the table of backend specifiers). For
example, <code class="docutils literal notranslate"><span class="pre">logtalk</span> <span class="pre">&#64;&gt;=</span> <span class="pre">3.36.0</span></code>.</p>
<p>When a pack also depends on an operating-system version (e.g., a pack
containing shared libraries with executable code), the
<code class="docutils literal notranslate"><span class="pre">os(Name,Machine)</span></code> compound term can also be used in place of
<code class="docutils literal notranslate"><span class="pre">Registry::Pack</span></code>. For example, <code class="docutils literal notranslate"><span class="pre">os('Darwin',x86_64)</span> <span class="pre">&#64;&gt;=</span> <span class="pre">'23.0.0'</span></code>.
Note that, in this case, the release is an atom. The operating-system
data (name, machine, and release) is queried using the corresponding
<code class="docutils literal notranslate"><span class="pre">os</span></code> library predicates (see the library documentation for details).</p>
</section>
<section id="pack-portability">
<h2>Pack portability<a class="headerlink" href="#pack-portability" title="Link to this heading"></a></h2>
<p>Ideally, packs are fully portable and can be used with all
Logtalk-supported Prolog backends. This can be declared by using the
atom <code class="docutils literal notranslate"><span class="pre">all</span></code> in the last argument of the <code class="docutils literal notranslate"><span class="pre">version/6</span></code> predicate (see
example above).</p>
<p>When a pack can only be used with a subset of the Prolog backends, the
last argument of the <code class="docutils literal notranslate"><span class="pre">version/6</span></code> predicate is a list of backend
identifiers (atoms):</p>
<ul class="simple">
<li><p>B-Prolog: <code class="docutils literal notranslate"><span class="pre">b</span></code></p></li>
<li><p>Ciao Prolog: <code class="docutils literal notranslate"><span class="pre">ciao</span></code></p></li>
<li><p>CxProlog: <code class="docutils literal notranslate"><span class="pre">cx</span></code></p></li>
<li><p>ECLiPSe: <code class="docutils literal notranslate"><span class="pre">eclipse</span></code></p></li>
<li><p>GNU Prolog: <code class="docutils literal notranslate"><span class="pre">gnu</span></code></p></li>
<li><p>JIProlog: <code class="docutils literal notranslate"><span class="pre">ji</span></code></p></li>
<li><p>XVM: <code class="docutils literal notranslate"><span class="pre">xvm</span></code></p></li>
<li><p>Quintus Prolog: <code class="docutils literal notranslate"><span class="pre">quintus</span></code></p></li>
<li><p>SICStus Prolog: <code class="docutils literal notranslate"><span class="pre">sicstus</span></code></p></li>
<li><p>SWI-Prolog: <code class="docutils literal notranslate"><span class="pre">swi</span></code></p></li>
<li><p>Tau Prolog: <code class="docutils literal notranslate"><span class="pre">tau</span></code></p></li>
<li><p>Trealla Prolog: <code class="docutils literal notranslate"><span class="pre">trealla</span></code></p></li>
<li><p>XSB: <code class="docutils literal notranslate"><span class="pre">xsb</span></code></p></li>
<li><p>YAP: <code class="docutils literal notranslate"><span class="pre">yap</span></code></p></li>
</ul>
</section>
<section id="pack-development">
<h2>Pack development<a class="headerlink" href="#pack-development" title="Link to this heading"></a></h2>
<p>To simplify pack development and testing, define a local registry and
add to it a pack specification with the development version available
from a local directory. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>version(
    <span class="m">0</span><span class="o">:</span><span class="m">11</span><span class="o">:</span><span class="m">0</span>,
    beta,
    <span class="s">&#39;file:///home/jdoe/work/my_awesome_library&#39;</span>,
    none,
    [],
    all
).
</pre></div>
</div>
<p>If the directory is a git repo, the tool will clone it when installing
the pack. Otherwise, the files in the directory are copied to the pack
installation directory. This allows the pack to be installed, updated,
and uninstalled without consequences for the pack source files.</p>
<p>You can also use a local archive instead of a directory. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>version(
    <span class="m">1</span><span class="o">:</span><span class="m">0</span><span class="o">:</span><span class="m">0</span>,
    stable,
    <span class="s">&#39;file:///home/jdoe/work/my_awesome_library/v1.0.0.tar.gz&#39;</span>,
    sha256 <span class="o">-</span> <span class="s">&#39;1944773afba1908cc6194297ff6b5ac649a844ef69a69b2bcdf267cfa8bfce1e&#39;</span>,
    [],
    all
).
</pre></div>
</div>
<p>Packs that are expected to be fully portable should always be checked by
loading them with the <code class="docutils literal notranslate"><span class="pre">portability</span></code> flag set to <code class="docutils literal notranslate"><span class="pre">warning</span></code>.</p>
<p>To check your pack manifest files, use the <code class="docutils literal notranslate"><span class="pre">packs::lint/0-2</span></code>
predicates after adding the registry that provides the packs.</p>
</section>
<section id="pack-handling">
<h2>Pack handling<a class="headerlink" href="#pack-handling" title="Link to this heading"></a></h2>
<p>Packs must be available from a defined registry. To list all packs that
are available for installation, use the <code class="docutils literal notranslate"><span class="pre">packs::available/0</span></code>
predicate:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>available.
</pre></div>
</div>
<p>To list all installed packs, call the <code class="docutils literal notranslate"><span class="pre">packs::installed/0</span></code> predicate:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>installed.
</pre></div>
</div>
<p>To list only the installed packs from a specific registry, call instead
the <code class="docutils literal notranslate"><span class="pre">packs::installed/1</span></code> predicate. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>installed(talkshow).
</pre></div>
</div>
<p>To know more about a specific pack, use the <code class="docutils literal notranslate"><span class="pre">packs::describe/1-2</span></code>
predicates. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>describe(bar).
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">packs::describe/2</span></code> predicate can be used when two or more
registries provide packs with the same name. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>describe(reg, bar).
</pre></div>
</div>
<p>To install the latest version of a pack, we can use the
<code class="docutils literal notranslate"><span class="pre">packs::install/1-4</span></code> predicates. In the most simple case, when a pack
name is unique among registries, we can use the <code class="docutils literal notranslate"><span class="pre">packs::install/1</span></code>
predicate. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>install(bar).
</pre></div>
</div>
<p>Any pack dependencies are also checked and installed or updated if
necessary. Other install predicates are available to disambiguate
between registries and to install a specific pack version.</p>
<p>Packs become available for loading immediately after successful
installation (no restarting of the Logtalk session is required). For
example, after the pack <code class="docutils literal notranslate"><span class="pre">bar</span></code> is installed, you can load it at the
top-level by typing:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> <span class="k">{</span>bar(loader)<span class="k">}</span>.
</pre></div>
</div>
<p>or load it from a loader file using the goal
<code class="docutils literal notranslate"><span class="pre">logtalk_load(bar(loader))</span></code>.</p>
<p>After updating the defined registries, outdated packs can be listed
using the <code class="docutils literal notranslate"><span class="pre">packs::outdated/0</span></code> predicate. You can update all outdated
packs by calling the <code class="docutils literal notranslate"><span class="pre">packs::update/0</span></code> predicate or update a single
pack using the <code class="docutils literal notranslate"><span class="pre">packs::update/1-2</span></code> predicates. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>update(bar).
</pre></div>
</div>
<p>By default, updating a pack fails if it would break any dependent pack
(the <code class="docutils literal notranslate"><span class="pre">force(true)</span></code> option, described below, can be used to force
updating in this case).</p>
<p>The tool provides versions of the pack install, update, and uninstall
predicates that accept a list of options:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">verbose(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">false</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">clean(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">false</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">update(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">false</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">force(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">false</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">compatible(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">true</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">checksum(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">true</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">checksig(Boolean)</span></code> (default is <code class="docutils literal notranslate"><span class="pre">false</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">git(Atom)</span></code> (extra command-line options; default is <code class="docutils literal notranslate"><span class="pre">''</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">downloader(Atom)</span></code> (downloader utility; default is <code class="docutils literal notranslate"><span class="pre">curl</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">curl(Atom)</span></code> (extra command-line options; default is <code class="docutils literal notranslate"><span class="pre">''</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">wget(Atom)</span></code> (extra command-line options; default is <code class="docutils literal notranslate"><span class="pre">''</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">gpg(Atom)</span></code> (extra command-line options; default is <code class="docutils literal notranslate"><span class="pre">''</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">tar(Atom)</span></code> (extra command-line options; default is <code class="docutils literal notranslate"><span class="pre">''</span></code>)</p></li>
</ul>
<p>Note that, by default, only compatible packs can be installed. To
install a pack that is incompatible with the current Logtalk version,
backend version, or operating-system version, use the <code class="docutils literal notranslate"><span class="pre">install/4</span></code> or
<code class="docutils literal notranslate"><span class="pre">update/3</span></code> predicates with the option <code class="docutils literal notranslate"><span class="pre">compatible(false)</span></code>.</p>
<p>When installing large packs over unreliable network conditions, you may
try switching the default downloader utility from <code class="docutils literal notranslate"><span class="pre">curl</span></code> to <code class="docutils literal notranslate"><span class="pre">wget</span></code>.</p>
<p>When a pack may already be installed, you can use the <code class="docutils literal notranslate"><span class="pre">update(true)</span></code>
option to ensure that the installation will be updated to the specified
version:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>install(reg, bar, <span class="m">1</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">2</span>, [update(<span class="k">true</span>)]).
</pre></div>
</div>
<p>When using a <code class="docutils literal notranslate"><span class="pre">checksig(true)</span></code> option to check a pack signature, it is
strongly advised that you also use the <code class="docutils literal notranslate"><span class="pre">verbose(true)</span></code> option. For
example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>install(reg, bar, <span class="m">1</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">2</span>, [verbose(<span class="k">true</span>), checksig(<span class="k">true</span>)]).
</pre></div>
</div>
<p>Note that the public key used to sign the pack archive must already be
present in your local system.</p>
<p>Downloading pack archives may require passing extra command-line options
to <code class="docutils literal notranslate"><span class="pre">curl</span></code> for authentication. A common solution is to use a personal
access token. The details depend on the server software. An example when
using GitHub:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>install(reg, bar, <span class="m">1</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">2</span>, [curl(<span class="s">&#39;--header &quot;Authorization: token foo42&quot;&#39;</span>)]).
</pre></div>
</div>
<p>Another example when using GitLab:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>install(reg, bar, <span class="m">1</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">2</span>, [curl(<span class="s">&#39;--header &quot;PRIVATE-TOKEN: foo42&quot;&#39;</span>)]).
</pre></div>
</div>
<p>Pack archives may be <code class="docutils literal notranslate"><span class="pre">gpg</span></code> encrypted. Encryption can be
passphrase-based, key-based, or both. When using only passphrase-based
encryption, the archive passphrase must be entered (if not cached) when
installing or updating a pack. In this case, the passphrase can be
entered interactively or using the <code class="docutils literal notranslate"><span class="pre">gpg/1</span></code> option. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>install(reg, bar, <span class="m">1</span><span class="o">:</span><span class="m">1</span><span class="o">:</span><span class="m">2</span>, [gpg(<span class="s">&#39;--batch --passphrase test123&#39;</span>)]).
</pre></div>
</div>
<p>See the <code class="docutils literal notranslate"><span class="pre">gpg</span></code> documentation for details. When using the <code class="docutils literal notranslate"><span class="pre">gpg/1</span></code>
option, you should be careful to not leak passphrases in, e.g., the
query history.</p>
<p>To uninstall a pack that you no longer need, use the
<code class="docutils literal notranslate"><span class="pre">packs::uninstall/1-2</span></code> predicates. By default, only packs with no
dependent packs can be uninstalled. You can print or get a list of the
packs that depend on a given pack by using the <code class="docutils literal notranslate"><span class="pre">packs::dependents/1-3</span></code>
predicates. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>dependents(reg, bar, <span class="nv">Dependents</span>).
</pre></div>
</div>
<p>See the tool API documentation on the
<a class="reference external" href="../../docs/packs_0.html">packs</a> object for other useful predicates.</p>
</section>
<section id="pack-documentation">
<h2>Pack documentation<a class="headerlink" href="#pack-documentation" title="Link to this heading"></a></h2>
<p>The path to the pack <code class="docutils literal notranslate"><span class="pre">README.md</span></code> file is printed when the pack is
installed or updated. It can also be retrieved at any time by using the
<code class="docutils literal notranslate"><span class="pre">readme/2</span></code> predicate. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>readme(lflat, <span class="nv">Path</span>).
</pre></div>
</div>
<p>Additional documentation may also be available from the pack home page,
which can be printed by using the <code class="docutils literal notranslate"><span class="pre">describe/1-2</span></code> predicates. For
example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>describe(lflat).

<span class="c">% Registry:    ...</span>
<span class="c">% Pack:        lflat</span>
<span class="c">% Description: L-FLAT - Logtalk Formal Language and Automata Toolkit</span>
<span class="c">% License:     MIT</span>
<span class="c">% Home:        https://github.com/l-flat/lflat</span>
<span class="c">% Versions:</span>
...
</pre></div>
</div>
<p>The pack API documentation can be generated using the <code class="docutils literal notranslate"><span class="pre">lgtdoc</span></code> tool
library and directory predicates (depending on the pack source files
organization). For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> <span class="k">{</span>lflat(loader)<span class="k">}</span>,
     <span class="k">{</span>lgtdoc(loader)<span class="k">}</span>,
     logtalk<span class="o">::</span>expand_library_path(lflat, <span class="nv">Path</span>),
     lgtdoc<span class="o">::</span>rdirectory(<span class="nv">Path</span>).
...
</pre></div>
</div>
<p>This query creates a <code class="docutils literal notranslate"><span class="pre">xml_docs</span></code> directory in the current directory.
The XML documentation files can then be converted into a final format,
e.g., HTML, using one of the scripts provided by the <code class="docutils literal notranslate"><span class="pre">lgtdoc</span></code> tool.
For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="err">$</span> cd xml_docs
<span class="err">$</span> lgt2html
</pre></div>
</div>
<p>For more details and alternatives, see the <code class="docutils literal notranslate"><span class="pre">lgtdoc</span></code> tool
documentation.</p>
<p>It is also possible to add API documentation and diagrams for all the
installed packs to the Logtalk distribution API documentation and
diagrams by calling the <code class="docutils literal notranslate"><span class="pre">build</span></code> and <code class="docutils literal notranslate"><span class="pre">update_svg_diagrams</span></code> scripts in
the <code class="docutils literal notranslate"><span class="pre">docs/apis/sources</span></code> directory with the <code class="docutils literal notranslate"><span class="pre">-i</span></code> option. See the
scripts documentation for more details.</p>
</section>
<section id="pinning-registries-and-packs">
<h2>Pinning registries and packs<a class="headerlink" href="#pinning-registries-and-packs" title="Link to this heading"></a></h2>
<p>Registries and packs can be <em>pinned</em> after installation to prevent
accidental updating or deleting, e.g., when using the batch <code class="docutils literal notranslate"><span class="pre">update/0</span></code>
predicate. This is useful when your application requires a specific
version or for security considerations (see below). For example, if we
want the <code class="docutils literal notranslate"><span class="pre">bar</span></code> pack to stay at its current installed version:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>pin(bar).
yes
</pre></div>
</div>
<p>After, any attempt to update or uninstall the pack will fail with an
error message:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>update(bar).
<span class="o">!</span>     <span class="nv">Cannot</span> update pinned pack<span class="o">:</span> bar
no

| <span class="o">?-</span> packs<span class="o">::</span>uninstall(bar).
<span class="o">!</span>     <span class="nv">Cannot</span> uninstall pinned pack<span class="o">:</span> bar
no
</pre></div>
</div>
<p>To enable the pack to be updated or uninstalled, the pack must first be
unpinned. Alternatively, the <code class="docutils literal notranslate"><span class="pre">force(true)</span></code> option can be used. Note
that if you force update a pinned pack, the new version will be
unpinned.</p>
<p>It’s also possible to pin (or unpin) all defined registries or installed
packs at once by using the <code class="docutils literal notranslate"><span class="pre">pin/0</span></code> (or <code class="docutils literal notranslate"><span class="pre">unpin/0</span></code>) predicates. But
note that registries added after or packs installed after will not be
automatically pinned.</p>
</section>
<section id="testing-packs">
<h2>Testing packs<a class="headerlink" href="#testing-packs" title="Link to this heading"></a></h2>
<p>Logtalk packs (as most Logtalk libraries, tools, and examples) are
expected to have a <code class="docutils literal notranslate"><span class="pre">tester.lgt</span></code> or <code class="docutils literal notranslate"><span class="pre">tester.logtalk</span></code> tests driver
file at the root of their directory, which can be used for both
automated and manual testing. For example, after installing the <code class="docutils literal notranslate"><span class="pre">foo</span></code>
pack:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> <span class="k">{</span>foo(tester)<span class="k">}</span>.
</pre></div>
</div>
<p>To test all installed packs, you can use the <code class="docutils literal notranslate"><span class="pre">logtalk_tester</span></code>
automation script from the installed packs directory, which you can
query using the goal:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span>| <span class="o">?-</span> packs<span class="o">::</span>prefix(<span class="nv">Directory</span>).
</pre></div>
</div>
<p>Note that running the packs tests, like simply loading the pack, can
result in calling arbitrary code, which can potentially harm your
system. Always take into account the security considerations discussed
below.</p>
</section>
<section id="security-considerations">
<h2>Security considerations<a class="headerlink" href="#security-considerations" title="Link to this heading"></a></h2>
<p>New pack registries should be examined before being added, specially if
public and from a previously unknown source. The same precautions should
be taken when adding or updating a pack. Note that a registry can always
index third-party packs.</p>
<p>Pack checksums are checked by default. But pack signatures are only
checked if requested, as packs are often unsigned. Care should be taken
when adding public keys for pack signers to your local system.</p>
<p>Registry and pack spec files, plus the registry loader file, are
compiled by term-expanding them so that only expected terms are actually
loaded and only expected <code class="docutils literal notranslate"><span class="pre">logtalk_load/2</span></code> goals with expected relative
file paths are allowed. Predicates defining URLs are discarded if the
URLs are neither <code class="docutils literal notranslate"><span class="pre">https://</span></code> nor <code class="docutils literal notranslate"><span class="pre">file://</span></code> URLs or if they contain
non-allowed characters (currently, only alpha-numeric ASCII characters
plus the ASCII <code class="docutils literal notranslate"><span class="pre">/</span></code>, <code class="docutils literal notranslate"><span class="pre">.</span></code>, <code class="docutils literal notranslate"><span class="pre">-</span></code>, and <code class="docutils literal notranslate"><span class="pre">_</span></code> characters are accepted).
But note that this tool makes no attempt to audit pack source files
themselves.</p>
<p>Registries and packs can always be pinned so that they are not
accidentally updated to a version that you may not have had the chance
to audit.</p>
</section>
<section id="best-practices">
<h2>Best practices<a class="headerlink" href="#best-practices" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p>Make available a new pack registry as a git repo. This simplifies
updating the registry and rolling back to a previous version.</p></li>
<li><p>Use registry and pack names that are valid unquoted atoms, thus
simplifying usage. Use descriptive names with underscores if necessary
to link words.</p></li>
<li><p>Name the registry and pack specification objects after their names
with a <code class="docutils literal notranslate"><span class="pre">_registry</span></code> or <code class="docutils literal notranslate"><span class="pre">_pack</span></code> suffix. Save the objects in files
named after the objects.</p></li>
<li><p>Create new pack versions from git tags.</p></li>
<li><p>If the sources of a pack are available from a git repo, consider using
signed commits and signed tags for increased security.</p></li>
<li><p>When a new pack version breaks backwards compatibility, list both the
old and the new versions on the pack specification file.</p></li>
<li><p>Pin registries and packs when specific versions are critical for your
work so that you can still easily batch update the remaining packs and
registries.</p></li>
<li><p>Include the <code class="docutils literal notranslate"><span class="pre">$LOGTALKPACKS</span></code> directory (or the default
<code class="docutils literal notranslate"><span class="pre">~/logtalk_packs</span></code> directory) on your regular backups.</p></li>
</ul>
</section>
<section id="installing-prolog-packs">
<h2>Installing Prolog packs<a class="headerlink" href="#installing-prolog-packs" title="Link to this heading"></a></h2>
<p>This tool can also be used to install Prolog packs that don’t use
Logtalk. After installing a <code class="docutils literal notranslate"><span class="pre">pl_pack</span></code> Prolog pack from a <code class="docutils literal notranslate"><span class="pre">pl_reg</span></code>
registry, it can be found in the <code class="docutils literal notranslate"><span class="pre">$LOGTALKPACKS/packs/pl_reg/pl_pack</span></code>
directory. When the <code class="docutils literal notranslate"><span class="pre">LOGTALKPACKS</span></code> environment variable is not
defined, the pack directory is by default
<code class="docutils literal notranslate"><span class="pre">~/logtalk_packs/packs/pl_reg/pl_pack</span></code>.</p>
<p>Different Prolog systems provide different solutions for locating Prolog
code. For example, several Prolog systems adopted the Quintus Prolog
<code class="docutils literal notranslate"><span class="pre">file_search_path/2</span></code> hook predicate. For these systems, a solution
could be to add a fact to this predicate for each installed Prolog pack.
For example, assuming a <code class="docutils literal notranslate"><span class="pre">pl_pack</span></code> Prolog pack:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">multifile</span>(file_search_path<span class="o">/</span><span class="m">2</span>).
<span class="p">:- </span><span class="k">dynamic</span>(file_search_path<span class="o">/</span><span class="m">2</span>).

file_search_path(library, <span class="s">&#39;$LOGTALKPACKS/packs/pl_pack&#39;</span>).
</pre></div>
</div>
<p>If the Prolog system also supports reading an initialization file at
startup, the above definition could be added there.</p>
</section>
<section id="help-with-warnings">
<h2>Help with warnings<a class="headerlink" href="#help-with-warnings" title="Link to this heading"></a></h2>
<p>Load the <code class="docutils literal notranslate"><span class="pre">tutor</span></code> tool to get help with selected warnings printed by
the <code class="docutils literal notranslate"><span class="pre">packs</span></code> tool.</p>
</section>
<section id="known-issues">
<h2>Known issues<a class="headerlink" href="#known-issues" title="Link to this heading"></a></h2>
<p>Using the <code class="docutils literal notranslate"><span class="pre">verbose(true)</span></code> option on Windows systems may not provide
the shell commands output depending on the backend.</p>
<p>On Windows systems, the reset, delete, and uninstall predicates may fail
to delete all affected folders and files due to a operating-system bug.
Depending on the backend, this bug may cause some of the tests to fail.
For details on this bug, see:</p>
<p><a class="reference external" href="https://github.com/microsoft/terminal/issues/309">https://github.com/microsoft/terminal/issues/309</a></p>
<p>The workaround is to use the Windows File Explorer to delete the
leftover folders and files.</p>
<p>When using Ciao Prolog 1.20.0, a workaround is used for this system
non-standard support for multifile predicates.</p>
<p>When using GNU Prolog 1.5.0 as the backend on Windows, you may get an
error on <code class="docutils literal notranslate"><span class="pre">directory_files/2</span></code> calls. For details and a workaround, see:</p>
<p><a class="reference external" href="https://github.com/didoudiaz/gprolog/issues/4">https://github.com/didoudiaz/gprolog/issues/4</a></p>
<p>This issue is fixed in the latest GNU Prolog git version.</p>
<p>Using SICStus Prolog as the backend on Windows doesn’t currently work in
version 4.7.0 and earlier versions. The underlying issues are fixed in
the SICStus Prolog 4.7.1 version.</p>
<p>XSB has an odd bug (likely in its parser) when reading files that may
cause a pack installed version to be reported as the <code class="docutils literal notranslate"><span class="pre">end_of_file</span></code>
atom.</p>
<p>Some tests fail on Windows when using ECLiPSe or XSB due to file path
representation issues.</p>
</section>
</section>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="make.html" class="btn btn-neutral float-left" title="make" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
        <a href="ports_profiler.html" class="btn btn-neutral float-right" title="ports_profiler" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 1998-2025, Paulo Moura.</p>
  </div>

  Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
    provided by <a href="https://readthedocs.org">Read the Docs</a>.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>